package ex;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class SomeClass {
    public void a() {
        try {
            b();
        } catch (Exception e) {
            throw new AException("111", e);
        }
    }

    public void b() {
        try {
            c();
        } catch (Exception e) {
            throw new BException("222", e);
        }
    }

    public void c() {
        throw new CException("333");
    }

    public static void main(String[] args) throws Exception {

        // reflectionCall();
        normalCall();
    }


    private static Throwable findRoot(Throwable e) {
        Throwable root = e;
        while (root != null) {
            if (root.getCause() == null) {
                break;
            }
            root = root.getCause();
        }
        return root;
    }

    static Throwable getRootCause(Throwable ex) {
        Throwable cause;
        Throwable root = ex;
        while (null != (cause = root.getCause()) && (root != cause)) {
            root = cause;
        }
        return root;
    }

    private static void normalCall() {
        SomeClass instance = new SomeClass();

        try {
            instance.a();
        } catch (Exception e) {
            System.out.println(e.getClass());
            //            System.out.println(e.getCause());
            //            System.out.println(e.getCause().getCause());
            //            System.out.println(e.getCause().getCause().getCause());
            System.out.println(findRoot(e));
            //System.out.println(getRootCause(e));
        }
    }

    private static void reflectionCall() throws Exception {
        SomeClass instance = new SomeClass();

        Method m = SomeClass.class.getDeclaredMethod("c");
        try {
            m.invoke(instance);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (IllegalArgumentException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }
}
